package star.cloud.asme.flowable.processDefinition;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;

import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.*;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import star.cloud.asme.base.dto.Result;
import star.cloud.asme.base.fowable.VO.ProcessDefinitionQueryCondition;
import star.cloud.asme.base.fowable.VO.ProcessDefinitionVO;
import star.cloud.asme.base.fowable.baseInterface.FlowableVOGeneratorService;
import star.cloud.asme.base.utils.ObjectsUtil;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
@Slf4j
public class HqProcessDefinitionServiceImpl implements HqProcessDefinitionService {

    private final RepositoryService repositoryService;

    private final FlowableVOGeneratorService voGeneratorService;

    @Override
    public Result<ProcessDefinitionVO> getOneByCondition(String key, Object value) {

        ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();

        switch (key) {
            case "id" -> definitionQuery.processDefinitionId(value.toString());
            case "key" -> definitionQuery.processDefinitionKey(value.toString()).latestVersion();
            case "name" -> definitionQuery.processDefinitionName(value.toString()).latestVersion();
            default -> log.info("没有的条件");
        }

        ProcessDefinition processDefinition = definitionQuery.singleResult();

        ProcessDefinitionVO processDefinitionVO = voGeneratorService.generateProcessDefinitionVO(processDefinition.getId());

        return Result.ok(processDefinitionVO);

    }

    @Override
    public Result<IPage<ProcessDefinitionVO>> getListByConditionsWithPage(ProcessDefinitionQueryCondition conditions) {

        IPage<ProcessDefinitionVO> iPage = new Page<>(conditions.getCurrentPage(), conditions.getPageSize());

        ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();

        if (ObjectsUtil.noNullAndEmpty(conditions.getProcessDefinitionKey())) {
            definitionQuery.processDefinitionKey(conditions.getProcessDefinitionKey());
        }

        if (ObjectsUtil.noNullAndEmpty(conditions.getProcessDefinitionName())) {
            definitionQuery.processDefinitionNameLike("%" + conditions.getProcessDefinitionName() + "%");
        }

        if (ObjectsUtil.noNullAndEmpty(conditions.getProcessDefinitionCategory())) {
            definitionQuery.processDefinitionCategoryLike("%" + conditions.getProcessDefinitionCategory() + "%");
        }

        if (ObjectsUtil.noNullAndEmpty(conditions.getProcessDefinitionKey())) {
            definitionQuery.processDefinitionKeyLike("%" + conditions.getProcessDefinitionKey() + "%");
        }

        if (ObjectsUtil.noNullAndEmpty(conditions.getDeploymentTenantId())) {
            definitionQuery.processDefinitionTenantId(String.valueOf(conditions.getDeploymentTenantId()));
        }

        if (conditions.getProcessDefinitionIsLatestVersion()) {
            definitionQuery.latestVersion();
        }

        iPage.setTotal(definitionQuery.count());

        List<ProcessDefinition> processDefinitionList = definitionQuery.listPage(voGeneratorService.firstResult(iPage), voGeneratorService.maxResults(iPage));

        List<ProcessDefinitionVO> processDefinitionVOList = new ArrayList<>();

        processDefinitionList.forEach(item -> processDefinitionVOList.add(voGeneratorService.generateProcessDefinitionVO(item.getId())));

        iPage.setRecords(processDefinitionVOList);

        return Result.ok(iPage);
    }

    @Override
    public Result<ProcessDefinitionVO> deploy(MultipartFile file, ProcessDefinitionVO processDefinitionVO) {
        try {
            Deployment deployment = repositoryService.createDeployment()//
                    .name(processDefinitionVO.getDeploymentName())//
                    .category(processDefinitionVO.getDeploymentCategory())//
                    .tenantId(String.valueOf(processDefinitionVO.getDeploymentTenantId()))//
                    .addInputStream(file.getOriginalFilename(), file.getInputStream())//
                    .deploy();
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult();
            repositoryService.setDeploymentKey(deployment.getId(), processDefinition.getKey());
            repositoryService.setProcessDefinitionCategory(processDefinition.getId(), processDefinitionVO.getDeploymentCategory());
            return Result.ok(voGeneratorService.generateProcessDefinitionVO(processDefinition.getId()));

        } catch (IOException e) {
            System.out.println(e.getMessage());
            return Result.error();
        }
    }

    @Override
    public Result<ProcessDefinitionVO> updateDeployment(ProcessDefinitionVO processDefinitionVO) {
        repositoryService.setDeploymentCategory(processDefinitionVO.getDeploymentId(), processDefinitionVO.getDeploymentCategory());
        repositoryService.setDeploymentKey(processDefinitionVO.getDeploymentId(), processDefinitionVO.getDeploymentKey());
        return null;
    }


    @Override
    public Result<?> suspendProcessDefinition(String type, String value) {
        if (type.equals("id")) {
            repositoryService.suspendProcessDefinitionById(value);
        } else if (type.equals("key")) {
            repositoryService.suspendProcessDefinitionByKey(value);
        } else {
            return Result.error();
        }
        return Result.ok();
    }

    @Override
    public Result<?> activateProcessDefinition(String type, String value) {
        if (type.equals("id")) {
            repositoryService.activateProcessDefinitionById(value);
        } else if (type.equals("key")) {
            repositoryService.activateProcessDefinitionByKey(value);
        } else {
            return Result.error();
        }
        return Result.ok();
    }

    @Override
    public Result<?> physicalDelete(String processDefinitionId) {
        String deploymentId = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult().getDeploymentId();
        if (deploymentId != null) {
            repositoryService.deleteDeployment(deploymentId, true);
            return Result.ok();
        }
        return Result.error();
    }


}
